Skip to content

feat(MAPCO-11434): let the worker bill a Claude subscription instead of an API key - #13

Open
razbroc wants to merge 1 commit into
feat/implement-and-verifyfrom
feat/subscription-auth
Open

feat(MAPCO-11434): let the worker bill a Claude subscription instead of an API key#13
razbroc wants to merge 1 commit into
feat/implement-and-verifyfrom
feat/subscription-auth

Conversation

@razbroc

@razbroc razbroc commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Stacked on #7 — review that first.

Question Answer
Bug fix
New feature
Breaking change
Deprecations
Documentation
Tests added
Chore

Adds a second authentication mode so the worker can bill a Claude subscription token instead of a metered Anthropic API key, and wires the Secret and README rows that were the unmet half of #7's first acceptance criterion.

⚠️ Read this before merging

Anthropic's Agent SDK documentation states:

Unless previously approved, Anthropic does not allow third party developers to offer claude.ai login or rate limits for their products, including agents built on the Claude Agent SDK.

This PR makes the mode reachable, not permitted. Setting MODEL_AUTH=subscription asserts that this deployment has that approval; no code can check it. api-key stays the default.

Three consequences no code can fix, recorded in both README.md and credential.ts:

  • Shared quota. Rate limits belong to the account, so the worker and that person's own interactive Claude Code use starve each other.
  • Attribution. Runs are that person's, not the worker's — the same problem the README already records for the shared Jira service account, now for the model.
  • Expiry. Subscription tokens lapse, and the pod crash-loops when one does. That is the intended failure, not a bug.

The mode is explicit, never inferred

The design decision worth reviewing. MODEL_AUTH is read from configuration; the worker does not pick whichever credential happens to be present.

Both credentials look alike to the SDK and bill completely differently. Inferring would make the billed party a property of the pod's environment rather than of a decision, and the failure mode is silent — a run that quietly spends someone's personal quota looks exactly like a working one. So:

  • One mode's credential is never used for the other.
  • When the expected one is missing and the other is set, the error names it. Setting a token and forgetting the mode is the mistake an operator actually makes.
  • An unrecognised mode refuses to start rather than falling back to the default, because a typo would otherwise bill the wrong account.

modelEnv now scrubs then injects

It previously injected ANTHROPIC_API_KEY over a partially-scrubbed environment. With two modes reading different variables, leaving the unused one in place would let the SDK pick the other — so every credential is scrubbed and exactly one goes back in, making the choice singular by construction. Tested in both modes.

What this closes on #7

  • The worker authenticates with a credential from an OpenShift Secret, never an interactive login — now genuinely both halves. helm/templates/deployment.yaml gets MODEL_AUTH plus a secretKeyRef for whichever credential the mode needs (apiKey or oauthToken from worker.modelSecretName), and the README documents all three variables.

Note the criterion's wording is now strained: subscription mode is an interactive-login credential, obtained with claude setup-token. It is opt-in, off by default, and the reason is in the file — but if you'd rather the ticket's wording hold literally, this PR is the thing to drop.

Verification

tsc --noEmit clean, eslint clean, 202 tests pass (17 files) on this branch.

Not verified: the chart change. helm template cannot run here — Error: found in Chart.yaml, but missing in charts/ directory: mclabels, the known gap the README already records. The template edit is unrendered. Worth a second pair of eyes on the {{- if eq .Values.worker.modelAuth "subscription" }} branch.

apiKey.ts is renamed to credential.ts, since it no longer reads only a key.

Refs: MAPCO-11434

MAPCO-11434. Adds a second authentication mode so a deployment can run against a
Claude subscription token rather than a metered Anthropic API key, and wires the
Secret and the docs that were the unmet half of the first acceptance criterion.

Which mode is in use is explicit configuration, `MODEL_AUTH`, and is never
inferred from whichever credential happens to be set. Both credentials look
alike to the SDK and bill completely differently, so inferring would make the
billed party a property of the pod's environment rather than of a decision — and
the failure is silent, because a run that quietly spends someone's personal quota
looks exactly like a working one. One mode's credential is never used for the
other; the worker refuses to start and names the one it found, since setting a
token and forgetting the mode is the mistake an operator actually makes. An
unrecognised mode also refuses rather than falling back to the default.

`modelEnv` now scrubs every credential and injects exactly one, the configured
mode's. Previously it injected ANTHROPIC_API_KEY over a partially-scrubbed
environment; with two modes reading different variables, leaving the unused one
in place would let the SDK pick the other.

Chart: MODEL_AUTH plus a secretKeyRef for whichever credential the mode needs,
from worker.modelSecretName. README documents both variables and the mode.

subscription mode is reachable, not blessed. Anthropic's Agent SDK documentation
states that claude.ai login and its rate limits may not be used for products
built on the Agent SDK unless previously approved, so setting the mode asserts
this deployment has that approval — code cannot check it. Three consequences no
code can fix are recorded in README.md and credential.ts: the quota is shared
with that person's own interactive use, runs are attributed to them rather than
to the worker, and the pod crash-loops when the token expires. api-key remains
the default for those reasons.

Renames apiKey.ts to credential.ts, since it no longer only reads a key.
@github-actions

Copy link
Copy Markdown

🎫 Related Jira Issue: MAPCO-11434

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant